perm filename IOV2.2[EAL,HE]1 blob sn#676457 filedate 1982-09-27 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	{$NOMAIN	Individual statement Interpreters }
C00005 00003	procedure doCase external
C00007 00004	procedure doCall external
C00008 00005	procedure doReturn external
C00012 00006	procedure doAssign external
C00014 00007	procedure doPrompt external
C00016 00008	procedure doSignal external
C00018 00009	procedure doWait external
C00020 ENDMK
C⊗;
{$NOMAIN	Individual statement Interpreters }

%include ialhdr.pas;

{ Externally defined routines: }

	(* From ALLOC *)
function newNode: nodep;					external;
procedure relNode(n: nodep);					external;

	(* From IAUX1A *)
function pop: nodep;						external;
function gtVarn (n: nodep): enventryp;				external;
procedure freePdb(p: pdbp);					external;
procedure killNode(n: nodep);					external;
procedure killStack;						external;

	(* From IAUX1B *)
procedure prntPlist(n: nodep);					external;
procedure prntVar(v: nodep);					external;
procedure addPdb(var plist: pdbp; pn: pdbp);			external;
procedure sleep(whenV: integer);				external;

	(* From IAUX2A *)
procedure killEnv;						external;
procedure setVal (level, offset: byte);				external;

	(* From IAUX2B *)
function cmonCheck: boolean;					external;

	(* From IROOT *)
procedure ov2FlushKids(p: pdbp; zapit: boolean);		external;

	(* Display-related Routines *)
procedure ppLine; 						external;
procedure ppOutNow; 						external;
procedure ppChar(ch: ascii); 					external;
procedure pp5(ch: c5str; length: integer); 			external;
procedure pp10(ch: cstring; length: integer); 			external;
procedure pp10L(ch: cstring; length: integer);			external;
procedure pp20(ch: c20str; length: integer); 			external;
procedure pp20L(ch: c20str; length: integer); 			external;
procedure ppInt(i: integer); 					external;
procedure ppReal(r: real); 					external;
procedure ppStrng(length: integer; s: strngp); 			external;


procedure iOv2Get; external;
procedure iOv2Get; begin end;
procedure doCase; external;
procedure doCase;
 var i: integer; p: nodep; spcp: statementp; b: boolean;
 begin
 with curInt↑ do
  begin
  p := pop;				(* pop index value off of stack *)
  i := round(p↑.s);
  relNode(p);
  spcp := nil;
  p := spc↑.caselist;
  if (i >= 0) and (i <= abs(spc↑.range)) then	(* index within range *)
    begin					(* try to find proper case *)
    b := true;
    while (p <> nil) and b do
     if (p↑.cval = i) then b := false else p := p↑.next;
    if p <> nil then
      begin spcp := p↑.stmnt; if spcp = nil then spcp := spc↑.next end
     else if spc↑.range >= 0 then spcp := spc↑.next (* null statement *)
    end;
  if (spcp = nil) and (spc↑.range < 0) then
    begin (* if none found and it's a labelled case statement check for else *)
    p := spc↑.caselist;
    b := true;
    while (p <> nil) and b do			(* search for else stmnt *)
     if (p↑.cval = -1) then b := false else p := p↑.next;
    if p <> nil then spcp := p↑.stmnt
    end;
  if spcp = nil then
    begin
    pp20L('Case index out of ra',20); pp5('nge: ',5); ppInt(i); ppLine;
    spcp := spc↑.next;
    end;
  spc := spcp;
  mode := 0;
  end;
 end;

procedure doCall; external;
procedure doCall;
 var n: nodep;
 begin
 with curInt↑ do
  begin
  if spc↑.what↑.arg1↑.vari↑.vtype <> nulltype then  (* flush unused result *)
    n := pop;
  mode := 0;
  spc := spc↑.next;	(* move on to next statement *);
  end;
 end;

procedure doReturn; external;
procedure doReturn;
 var p: pdbp; n: nodep; b,debRet: boolean; 
 begin
 b := true;
 with curInt↑ do
  begin
  if procp then debRet := false			(* normal case *)
   else if (priority > 9) and (nextpdb = nil) and (opdb <> nil) then
    debRet := true			(* immediately executed RETURN *)
   else b := false;			(* no good - nothing to return from *)
  if debRet then p := opdb↑.opdb else p := opdb;	(* pdb of caller *)
  if b then
    begin
    while b and not env↑.procp do
     begin	(* make sure all cmon's in outer environments have finished *)
     b := cmonCheck;
     if b then killEnv;		(* flush all environments out to parameters *)
     end;
    if b then			(* no cmons now running *)
      begin	(* now we can clean things up & return from the procedure *)
      if spc↑.retval <> nil then n := pop		(* get return value *)
       else n := nil;
      if env↑.proc↑.ptype <> nulltype then
	begin			(* yes - put return value on caller's stack *)
	if n <> nil then
	  if env↑.proc↑.ptype <> n↑.ltype then
	    begin
	    killNode(n);
	    n := nil;
	    end;
	if n = nil then
	  begin
	  n := newNode;
	  with n↑ do		(* use default value *)
	   begin
	   ntype := leafnode;
	   ltype := env↑.proc↑.ptype;	(* copy datatype of result *)
	   if ltype = svaltype then s := 0.0	(* it's a scalar *)
	    else if ltype = vectype then v := nilvect
	    else if ltype = transtype then t := niltrans
	    else begin length := 0; str := nil end;
	    end;
	  end;
	n↑.next := p↑.sp;
	p↑.sp := n;
	end;
      killEnv;				(* flush procedure's parameters too *)
      killStack;			(* flush stack *)
      if debRet then
	begin
	opdb↑.opdb↑.status := runqueue;
	addPdb(activeInts,opdb↑.opdb);	(* re-activate caller *)
	opdb↑.level := 255;		(* so we don't re-release environments *)
	ov2FlushKids(opdb,true);	(* flush old procedure's pdb *)
	spc := sdef↑.next;		(* point to our abort *)
	running := false;		(* and return to debugger *)
	end
       else
	begin
	freePdb(curInt);		(* flush procedure's pdb *)
	curInt := p;			(* all done - return *)
	curInt↑.status := nowrunning;
	end;
      end
     else sleep(30);			(* give cmons time to finish *)
    end
   else
    begin
    pp20L('Ignoring return     ',16); ppLine;
    if spc↑.retval <> nil then n := pop;	(* flush return value *)
    spc := spc↑.next;			(* just move on to next statement *)
    mode := 0;
    end;
  end;
 end;

procedure doAssign; external;
procedure doAssign;
 var ev: enventryp; res: nodep;
 begin
 with curInt↑.spc↑.what↑ do
  begin
  if ntype = leafnode then 
    with vari↑ do setVal(level,offset) (* store into simple variable *)
   else
    case op of		(* see what type of store we're to do *)
arefop:	    with arg1↑.vari↑ do setVal(level,offset); (* store into array var *)
deproachop: begin	  (* any subscripts & deproach value on stack *)
	    ev := gtVarn(curInt↑.spc↑.what);	  (* access variable *)
	    res := pop;			  (* get deproach value *)
	    (* check we've really got a frame? *)
	    ev↑.f↑.fdepr := res↑.t;	  (* store it away *)
	    relNode(res);
	    end;
tposop,
torientop:  begin
	    with arg1↑ do
	     if ntype = leafnode then 
		with vari↑ do setVal(level,offset) (* simple variable *)
	       else
		with arg1↑.vari↑ do setVal(level,offset);  (* array variable *)
	    end;
otherwise   {do nothing};
    end;
  curInt↑.mode := 0;
  curInt↑.spc := curInt↑.spc↑.next;	(* move on to next statement *);
  end;
 end;

procedure doPrompt; external;
procedure doPrompt;
 var ch: ascii; b: boolean;
 begin
 with curInt↑ do
  case mode of
1:  begin
    if readQueue = nil then b := true
     else b := (readQueue↑.priority div 10) < (curInt↑.priority div 10);
    if b then 
      begin			(* first time through *)
      prntplist(spc↑.plist);
      mode := 2;
      end
     else sleep(60)		(* wait a sec for other input to finish *)
    end;

2:  begin
    pp20L('Type P to proceed:  ',19);
    ppOutNow;
    mode := 3;
    curInt↑.next := readQueue;
    readQueue := curInt;			(* swap us out *)
    curInt↑.status := inputqueue;
    curInt := nil;
    inputp := 0;
    resched := true;
    end;

3:  begin
    inputReady := false;
    if (inputLine[1] = chr(160B)) or (inputLine[1] = 'P') then
      begin
      mode := 0;
      spc := spc↑.next;
      end
     else mode := 2;			(* try again *)
    end;

   end;
 end;

procedure doSignal; external;
procedure doSignal;
 var ev: enventryp; p, pt: pdbp; st: statementp;
 begin
 with curInt↑ do
  begin
  st := spc;
  spc := spc↑.next;	(* advance our pc now before possibly swapping ourself out *)
  mode := 0;
  if singleThreadMode then
    begin
    pp20L('Would signal event: ',20); prntVar(st↑.event);
    end
   else if st↑.event <> nil then
    begin
    ev := gtVarn(st↑.event);	(* access variable *)
    ev↑.evt↑.count := ev↑.evt↑.count + 1;
    p := ev↑.evt↑.waitlist;	(* get pdb of process to schedule (if any) *)
    if p <> nil then 
      begin
      ev↑.evt↑.waitlist := p↑.next;		(* remove node from waitlist *)
      if p↑.priority > priority then
	begin				(* swap it in and swap us out *)
	p↑.status := nowrunning;
	pt := curInt;
	curInt := p;
	p := pt;
	end;
      p↑.status := runqueue;
      addPdb(activeInts,p);		(* add whoever to active process list *)
      end;
    end;
  end;
 end;

procedure doWait; external;
procedure doWait;
 var ev: enventryp; p: pdbp; st: statementp; b: boolean;
 begin
 with curInt↑ do
  if singleThreadMode then
    if mode = 1 then
      begin
      if readQueue = nil then b := true
       else b := (readQueue↑.priority div 10) < (curInt↑.priority div 10);
      if b then 
	begin			(* first time through *)
	pp20L('Would wait for event',20); pp5(':    ',2); prntVar(spc↑.event);
	mode := 2;
	doPrompt;		(* now have user type a "P" to proceed *)
	end
       else sleep(60)		(* wait a sec for other input to finish *)
      end
     else doPrompt
   else
    begin
    st := spc;
    spc := spc↑.next;	(* advance our pc now before maybe swapping out *)
    mode := 0;
    if st↑.event <> nil then
      begin
      ev := gtVarn(st↑.event);		(* access variable *)
      ev↑.evt↑.count := ev↑.evt↑.count - 1;
      if ev↑.evt↑.count < 0 then 	(* hasn't been signalled yet, need to wait *)
	begin
	curInt↑.status := eventqueue;
	addPdb(ev↑.evt↑.waitlist,curInt);	(* add us to wait list *)
	curInt := nil;			(* swap in someone else *)
	resched := true;
	end;
      end;
    end;
 end;